﻿using System;
using DotNet.DevOps.Tasks.Service.Helpers;
using DotNet.DevOps.Tasks.Util;
using Microsoft.Build.Framework;

namespace DotNet.DevOps.Tasks.Service
{
    public interface IStopService
    {
        string Name { get; set; }
        string Machine { get; set; }
        int Timeout { get; set; }
    }

    /// <summary>
    /// Can stop a windows service on a local or remote machine.
    /// It is possible to define timeout for operation to complete.
    /// 
    /// Requirements:
    /// * The user under which the task is executed must have the correct rights to stop on the local/remote machine.
    /// 
    /// </summary>
    /// <example>
    /// import-module .\DotNet.DevOps.Tasks.dll
    /// 
    /// $task = New-Object DotNet.DevOps.Tasks.Service.StopService -Property @{
    ///                                                                 Name="MyService" 
    ///                                                                 Machine="TESTSERVER" 
    ///                                                                 Timeout="30000"
    ///                                                              }
    /// $result = $task.Execute()
    /// </example>
    /// <example>
    /// <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    /// 
    ///  <UsingTask TaskName="StopService" AssemblyFile="$(OutputDir)\DotNet.DevOps.Tasks.dll" />
    /// 
    ///  <Target Name="Build">
    /// 
    ///    <StopService     Name="MyService" 
    ///                     Machine="TESTSERVER" 
    ///                     Timeout="30000" />
    /// 
    ///  </Target>
    /// 
    /// </Project>
    /// </example>
    public class StopService : ITask, IStopService
    {
        public IBuildEngine BuildEngine { get; set; }
        public ITaskHost HostObject { get; set; }

        /// <summary>
        /// Name of the service to stop.
        /// </summary>
        [Required]
        public string Name { get; set; }


        private string _machine;
        /// <summary>
        /// Name of the machine on which to stop the service. Default to this machine.
        /// </summary>
        [Standard]
        public string Machine
        {
            get
            {
                return string.IsNullOrWhiteSpace(_machine) == true ? Environment.MachineName : _machine;
            }

            set { _machine = value; }
        }

       
        /// <summary>
        /// Complete timeout, in milliseconds, for all the service command which might fire (Stop). Default infinte.
        /// </summary>
        [Standard]
        public int Timeout { get; set; }

        private ILog Log { get; set; }

        public StopService()
        {
            Init();
            Log = new MSBuildLogger(this);
        }

        public StopService(ILog log)
        {
            Init();
            Log = log;
        }

        private void Init()
        {
            Timeout = -1;
        }

        public bool Execute()
        {
            try
            {
                new ServiceControl(Log)
                            {
                                CommandTimeout = Timeout,
                                Machine = Machine,
                                Name = Name,
                            }.Stop();
            }
            catch (Exception ex)
            {
                Log.LogError(ex);
                return false;
            }

            return true;
        }
    }
}
